<?php
/**
 * Created by PhpStorm
 * User: shen.zk
 * Date: 2023/8/28
 * Time: 19:03
 * Comment: ''
 */

namespace App\Extensions\bservice;

use App\Jobs\ApplylogJob;
use App\Traits\HttpHelper;
use App\Common\ResponseCode;
use App\Exceptions\BusinessException;
use Illuminate\Support\Facades\Log;
use App\Common\Tools;

class Bservice
{
    use HttpHelper;

    // 请求domain
    protected $host;
    // 请求accessMid
    protected $accessMid;
    // 请求busiSceneNo
    protected $busiSceneNo;
    // 请求contractMid
    protected $contractMid;
    // 请求funcProductNo
    protected $funcProductNo;
    // 请求marketProductNo
    protected $marketProductNo;
    // 请求transNo
    protected $transNo;
    // 请求transFrom
    protected $transFrom;
    // 请求accessFrom
    protected $accessFrom;
    // 请求domain
    protected $accessSystemNo;
    // 请求token
    protected $token;
    // 密钥文件
    protected $priKey;
    // 代理配置
    protected $proxy =[];

    // 定义请求头部信息
    protected $headers = [
        'version:ver1.0.0',
        'charset:UTF-8',
        'Content-Type:application/json; charset=UTF-8'
    ];

    public function __construct()
    {
        // 初始化配置參數
        $this->host = config('authentication.authentication_host');
        $this->accessMid = config('authentication.authentication_accessmid');
        $this->busiSceneNo = config('authentication.authentication_busisceneno');
        $this->contractMid = config('authentication.authentication_contractmid');
        $this->funcProductNo = config('authentication.authentication_funcproductno');
        $this->marketProductNo = config('authentication.authentication_marketproductno');
        $this->transNo = config('authentication.authentication_transno');
        $this->transFrom = config('authentication.authentication_transfrom');
        $this->accessFrom = config('authentication.authentication_accessfrom');
        $this->accessSystemNo = config('authentication.authentication_accesssystemno');
        $this->token = config('authentication.authentication_token');
        $this->priKey = config('authentication.authentication_prikey');
    }

    public static function getInstance(){
        return new self();
    }

    /**
     * 組裝公用請求參數
     * @return array
     * @author shen.zk
     * @date 2023-08-28 19:48
     */
    protected function createCommon()
    {
        $data = [];
        $data['body']['accessMid'] = $this->accessMid;
        $data['body']['busiSceneNo'] = $this->busiSceneNo;
        $data['body']['contractMid'] = $this->contractMid;
        $data['body']['customerOrderNo'] = Tools::build_hash_no();
        $data['body']['funcProductNo'] = $this->funcProductNo;
        $data['body']['marketProductNo'] = $this->marketProductNo;
        $data['body']['transNo'] = $this->transNo;
        $data['head']['transFrom'] = $this->transFrom;
        $data['head']['accessFrom'] = $this->accessFrom;
        $data['head']['accessSystemNo'] = $this->accessSystemNo;
        $data['head']['timestamp'] = date("YmdHis");
        $data['head']['accessSerialNo'] = $data['body']['customerOrderNo'];
        $data['head']['token'] = $this->token;
        return $data;
    }

    /**
     * 实名认证请求
     * @param string $idcard
     * @param string $name
     * @return mixed
     * @throws BusinessException
     * @author shen.zk
     * @date 2023-09-04 14:53
     */
    public function authenticationInfo(string $idcard,string $name)
    {
        $requestParams = $this->createCommon();
        $requestParams['body']['bizInfo']['idcard'] = $idcard;
        $requestParams['body']['bizInfo']['username'] = $name;
        return $this->sendRequestPost($requestParams);
    }

    /**
     * 发起请求
     * @param array $data
     * @return mixed
     * @throws BusinessException
     * @author shen.zk
     * @date 2023-09-04 14:52
     */
    protected function sendRequestPost(array $data)
    {
        Log::info('[实名认证]请求原始参数'.json_encode($data,JSON_UNESCAPED_UNICODE));

        // 键升序排序
        ksort($data);
        ksort($data['body']);
        ksort($data['head']);
        Log::info('[实名认证]请求排序参数'.json_encode($data,JSON_UNESCAPED_UNICODE));

        // 生成签名参数
        $signParams = urldecode(http_build_query($data));
        Log::info('[实名认证]生成签名参数'.$signParams);

        $sign = $this->createRsasign($signParams);
        Log::info('[实名认证]签名返回'.$sign);
        $data['sign'] = $sign;

        $bodys = json_encode($data, JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE);
        // print_r($bodys);
        $url = $this->host;
        $method = "POST";
        $headers = array();
        array_push($headers, "version:ver1.0.0");
        array_push($headers, "charset:UTF-8");
        //根据API的要求，定义相对应的Content-Type
        array_push($headers, "Content-Type" . ":" . "application/json; charset=UTF-8");
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($curl, CURLOPT_FAILONERROR, false);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_HEADER, false);
        if (1 == strpos("$" . $url, "https://")) {
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        }
        curl_setopt($curl, CURLOPT_POSTFIELDS, $bodys);
        //记录三方日志
        $response = curl_exec($curl);
        Log::info("[实名认证]返回数据：{$response}");

        // 异步处理
        $log = [
            'action'=>$this->host,
            'apply_info'=>json_encode($data,JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE),
            'result_info'=>$response,
            'create_time'=>date('Y-m-d H:i:s'),
            'type'=>'实名'
        ];

        dispatch(new ApplylogJob($log));

        if (empty($response))
            throw new BusinessException(ResponseCode::API_ACCESS_ERROR, ['error' => '服务异常']);

        $result = json_decode($response, true);

        return $result;
    }

    /**
     * 密钥加密请求参数
     * @param $data
     * @return string
     * @throws BusinessException
     * @author shen.zk
     * @date 2023-09-04 14:15
     */
    protected function createRsasign($data) {

        try {
            $priKey = $this->priKey;
            if (empty($priKey))
                throw new BusinessException(ResponseCode::PARAM_ILLEGAL,['error'=>'认证加密错误']);

            //转换为openssl密钥，必须是没有经过pkcs8转换的私钥
            $res = openssl_get_privatekey(file_get_contents($priKey));

            //调用openssl内置签名方法，生成签名$sign
            openssl_sign($data, $sign, $res);

            //释放资源
            openssl_free_key($res);

            //base64编码
            $sign = base64_encode($sign);

            return $sign;
        }catch (\Exception $e)
        {
            Log::error('[实名认证]密钥加密错误'.$e->getMessage());
            throw new BusinessException(ResponseCode::PARAM_ILLEGAL,['error'=>'认证加密错误']);
            return '';
        }

    }
}
